using System;
using System.Reflection;

namespace SqInterface.Utils
{
	/// <summary>
	/// Provides reflection helper methods.
	/// </summary>
	public sealed class Reflector
	{
		private Reflector() {}

		public static object CreateInstance( Assembly assembly, string name, params object[] parameters )
		{
			if( assembly == null )
			{
				throw new ArgumentNullException( "assembly" );
			}

			return CreateInstance( assembly.GetType( name ), parameters );
		}

		public static object CreateInstance( Type type, params object[] parameters )
		{
			return Activator.CreateInstance(
				type,
				BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
				null,
				parameters,
				null
				);
		}

		public static object InvokeMethod( Type type, string name, object instance, params object[] parameters )
		{
			return InvokeMember( type, name, instance, BindingFlags.InvokeMethod | BindingFlags.Instance, parameters );
		}
 
		public static object GetProperty( Type type, string name, object instance )
		{
			return InvokeMember( type, name, instance, BindingFlags.GetProperty | BindingFlags.Instance );
		}
 
		public static object SetProperty( Type type, string name, object instance, object value )
		{
			return InvokeMember( type, name, instance, BindingFlags.SetProperty | BindingFlags.Instance, value );
		}
 
		public static object GetField( Type type, string name, object instance )
		{
			return InvokeMember( type, name, instance, BindingFlags.GetField | BindingFlags.Instance );
		}
 
		public static object SetField( Type type, string name, object instance, object value )
		{
			return InvokeMember( type, name, instance, BindingFlags.SetField | BindingFlags.Instance, value );
		}

		public static object InvokeStaticMethod( Type type, string name, params object[] parameters )
		{
			return InvokeMember( type, name, null, BindingFlags.InvokeMethod | BindingFlags.Static, parameters );
		}

		public static object InvokeMember( Type type, string name, object instance, BindingFlags flags, params object[] parameters )
		{
			return type.InvokeMember( 
				name, 
				BindingFlags.Public | BindingFlags.NonPublic | flags,
				null,
				instance,
				parameters
				);
		}
	}
}
